home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / AvantBrowser / asetup.exe / _data / webkit / resources.pak / Unnamed File 000056.txt < prev    next >
Text File  |  2013-04-03  |  9KB  |  312 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. /**
  6.  * @fileoverview A command is an abstraction of an action a user can do in the
  7.  * UI.
  8.  *
  9.  * When the focus changes in the document for each command a canExecute event
  10.  * is dispatched on the active element. By listening to this event you can
  11.  * enable and disable the command by setting the event.canExecute property.
  12.  *
  13.  * When a command is executed a command event is dispatched on the active
  14.  * element. Note that you should stop the propagation after you have handled the
  15.  * command if there might be other command listeners higher up in the DOM tree.
  16.  */
  17.  
  18. cr.define('cr.ui', function() {
  19.  
  20.   /**
  21.    * This is used to identify keyboard shortcuts.
  22.    * @param {string} shortcut The text used to describe the keys for this
  23.    *     keyboard shortcut.
  24.    * @constructor
  25.    */
  26.   function KeyboardShortcut(shortcut) {
  27.     var mods = {};
  28.     var ident = '';
  29.     shortcut.split('-').forEach(function(part) {
  30.       var partLc = part.toLowerCase();
  31.       switch (partLc) {
  32.         case 'alt':
  33.         case 'ctrl':
  34.         case 'meta':
  35.         case 'shift':
  36.           mods[partLc + 'Key'] = true;
  37.           break;
  38.         default:
  39.           if (ident)
  40.             throw Error('Invalid shortcut');
  41.           ident = part;
  42.       }
  43.     });
  44.  
  45.     this.ident_ = ident;
  46.     this.mods_ = mods;
  47.   }
  48.  
  49.   KeyboardShortcut.prototype = {
  50.     /**
  51.      * Whether the keyboard shortcut object matches a keyboard event.
  52.      * @param {!Event} e The keyboard event object.
  53.      * @return {boolean} Whether we found a match or not.
  54.      */
  55.     matchesEvent: function(e) {
  56.       if (e.keyIdentifier == this.ident_) {
  57.         // All keyboard modifiers needs to match.
  58.         var mods = this.mods_;
  59.         return ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'].every(function(k) {
  60.           return e[k] == !!mods[k];
  61.         });
  62.       }
  63.       return false;
  64.     }
  65.   };
  66.  
  67.   /**
  68.    * Creates a new command element.
  69.    * @constructor
  70.    * @extends {HTMLElement}
  71.    */
  72.   var Command = cr.ui.define('command');
  73.  
  74.   Command.prototype = {
  75.     __proto__: HTMLElement.prototype,
  76.  
  77.     /**
  78.      * Initializes the command.
  79.      */
  80.     decorate: function() {
  81.       CommandManager.init(this.ownerDocument);
  82.  
  83.       if (this.hasAttribute('shortcut'))
  84.         this.shortcut = this.getAttribute('shortcut');
  85.     },
  86.  
  87.     /**
  88.      * Executes the command by dispatching a command event on the given element.
  89.      * If |element| isn't given, the active element is used instead.
  90.      * If the command is {@code disabled} this does nothing.
  91.      * @param {HTMLElement=} opt_element Optional element to dispatch event on.
  92.      */
  93.     execute: function(opt_element) {
  94.       if (this.disabled)
  95.         return;
  96.       var doc = this.ownerDocument;
  97.       if (doc.activeElement) {
  98.         var e = new cr.Event('command', true, false);
  99.         e.command = this;
  100.  
  101.         (opt_element || doc.activeElement).dispatchEvent(e);
  102.       }
  103.     },
  104.  
  105.     /**
  106.      * Call this when there have been changes that might change whether the
  107.      * command can be executed or not.
  108.      * @param {Node=} opt_node Node for which to actuate command state.
  109.      */
  110.     canExecuteChange: function(opt_node) {
  111.       dispatchCanExecuteEvent(this,
  112.                               opt_node || this.ownerDocument.activeElement);
  113.     },
  114.  
  115.     /**
  116.      * The keyboard shortcut that triggers the command. This is a string
  117.      * consisting of a keyIdentifier (as reported by WebKit in keydown) as
  118.      * well as optional key modifiers joinded with a '-'.
  119.      *
  120.      * Multiple keyboard shortcuts can be provided by separating them by
  121.      * whitespace.
  122.      *
  123.      * For example:
  124.      *   "F1"
  125.      *   "U+0008-Meta" for Apple command backspace.
  126.      *   "U+0041-Ctrl" for Control A
  127.      *   "U+007F U+0008-Meta" for Delete and Command Backspace
  128.      *
  129.      * @type {string}
  130.      */
  131.     shortcut_: '',
  132.     get shortcut() {
  133.       return this.shortcut_;
  134.     },
  135.     set shortcut(shortcut) {
  136.       var oldShortcut = this.shortcut_;
  137.       if (shortcut !== oldShortcut) {
  138.         this.keyboardShortcuts_ = shortcut.split(/\s+/).map(function(shortcut) {
  139.           return new KeyboardShortcut(shortcut);
  140.         });
  141.  
  142.         // Set this after the keyboardShortcuts_ since that might throw.
  143.         this.shortcut_ = shortcut;
  144.         cr.dispatchPropertyChange(this, 'shortcut', this.shortcut_,
  145.                                   oldShortcut);
  146.       }
  147.     },
  148.  
  149.     /**
  150.      * Whether the event object matches the shortcut for this command.
  151.      * @param {!Event} e The key event object.
  152.      * @return {boolean} Whether it matched or not.
  153.      */
  154.     matchesEvent: function(e) {
  155.       if (!this.keyboardShortcuts_)
  156.         return false;
  157.  
  158.       return this.keyboardShortcuts_.some(function(keyboardShortcut) {
  159.         return keyboardShortcut.matchesEvent(e);
  160.         });
  161.       }
  162.   };
  163.  
  164.   /**
  165.    * The label of the command.
  166.    * @type {string}
  167.    */
  168.   cr.defineProperty(Command, 'label', cr.PropertyKind.ATTR);
  169.  
  170.   /**
  171.    * Whether the command is disabled or not.
  172.    * @type {boolean}
  173.    */
  174.   cr.defineProperty(Command, 'disabled', cr.PropertyKind.BOOL_ATTR);
  175.  
  176.   /**
  177.    * Whether the command is hidden or not.
  178.    * @type {boolean}
  179.    */
  180.   cr.defineProperty(Command, 'hidden', cr.PropertyKind.BOOL_ATTR);
  181.  
  182.   /**
  183.    * Whether the command is checked or not.
  184.    * @type {boolean}
  185.    */
  186.   cr.defineProperty(Command, 'checked', cr.PropertyKind.BOOL_ATTR);
  187.  
  188.   /**
  189.    * Dispatches a canExecute event on the target.
  190.    * @param {cr.ui.Command} command The command that we are testing for.
  191.    * @param {Element} target The target element to dispatch the event on.
  192.    */
  193.   function dispatchCanExecuteEvent(command, target) {
  194.     var e = new CanExecuteEvent(command, true);
  195.     target.dispatchEvent(e);
  196.     command.disabled = !e.canExecute;
  197.   }
  198.  
  199.   /**
  200.    * The command managers for different documents.
  201.    */
  202.   var commandManagers = {};
  203.  
  204.   /**
  205.    * Keeps track of the focused element and updates the commands when the focus
  206.    * changes.
  207.    * @param {!Document} doc The document that we are managing the commands for.
  208.    * @constructor
  209.    */
  210.   function CommandManager(doc) {
  211.     doc.addEventListener('focus', this.handleFocus_.bind(this), true);
  212.     // Make sure we add the listener to the bubbling phase so that elements can
  213.     // prevent the command.
  214.     doc.addEventListener('keydown', this.handleKeyDown_.bind(this), false);
  215.   }
  216.  
  217.   /**
  218.    * Initializes a command manager for the document as needed.
  219.    * @param {!Document} doc The document to manage the commands for.
  220.    */
  221.   CommandManager.init = function(doc) {
  222.     var uid = cr.getUid(doc);
  223.     if (!(uid in commandManagers)) {
  224.       commandManagers[uid] = new CommandManager(doc);
  225.     }
  226.   };
  227.  
  228.   CommandManager.prototype = {
  229.  
  230.     /**
  231.      * Handles focus changes on the document.
  232.      * @param {Event} e The focus event object.
  233.      * @private
  234.      */
  235.     handleFocus_: function(e) {
  236.       var target = e.target;
  237.       var commands = Array.prototype.slice.call(
  238.           target.ownerDocument.querySelectorAll('command'));
  239.  
  240.       commands.forEach(function(command) {
  241.         dispatchCanExecuteEvent(command, target);
  242.       });
  243.     },
  244.  
  245.     /**
  246.      * Handles the keydown event and routes it to the right command.
  247.      * @param {!Event} e The keydown event.
  248.      */
  249.     handleKeyDown_: function(e) {
  250.       var target = e.target;
  251.       var commands = Array.prototype.slice.call(
  252.           target.ownerDocument.querySelectorAll('command'));
  253.  
  254.       for (var i = 0, command; command = commands[i]; i++) {
  255.         if (!command.disabled && command.matchesEvent(e)) {
  256.           e.preventDefault();
  257.           // We do not want any other element to handle this.
  258.           e.stopPropagation();
  259.  
  260.           command.execute();
  261.           return;
  262.         }
  263.       }
  264.     }
  265.   };
  266.  
  267.   /**
  268.    * The event type used for canExecute events.
  269.    * @param {!cr.ui.Command} command The command that we are evaluating.
  270.    * @extends {Event}
  271.    * @constructor
  272.    * @class
  273.    */
  274.   function CanExecuteEvent(command) {
  275.     var e = command.ownerDocument.createEvent('Event');
  276.     e.initEvent('canExecute', true, false);
  277.     e.__proto__ = CanExecuteEvent.prototype;
  278.     e.command = command;
  279.     return e;
  280.   }
  281.  
  282.   CanExecuteEvent.prototype = {
  283.     __proto__: Event.prototype,
  284.  
  285.     /**
  286.      * The current command
  287.      * @type {cr.ui.Command}
  288.      */
  289.     command: null,
  290.  
  291.     /**
  292.      * Whether the target can execute the command. Setting this also stops the
  293.      * propagation.
  294.      * @type {boolean}
  295.      */
  296.     canExecute_: false,
  297.     get canExecute() {
  298.       return this.canExecute_;
  299.     },
  300.     set canExecute(canExecute) {
  301.       this.canExecute_ = !!canExecute;
  302.       this.stopPropagation();
  303.     }
  304.   };
  305.  
  306.   // Export
  307.   return {
  308.     Command: Command,
  309.     CanExecuteEvent: CanExecuteEvent
  310.   };
  311. });
  312.